#include "GThread.h"
#include "GError.h"

namespace GThread
{
	G_DEFINE_DEBUG_NAME(GThread);

	static G_THREAD_LOCAL GThread* ThisThread  = NULL;

	// Description: Wrapper method for thread entry point.
	// Return: Return is same as thread method.
	// Notes: This method is for managing thread states. Also calls the main entry method.
	// ----------------------------------------------------
	GUInt32 __stdcall ThreadEntryMethod(void* Parameters) 
	{
		ThisThread = (GThread*)Parameters;
		ThisThread->State.store(G_TS_RUNNING, std::memory_order_release);

		void* Param = ThisThread->GetParameters();
		GEntryMethod Method = ThisThread->GetEntryMethod();

		GUInt32 Result = (*Method)(Param);

		ThisThread->State.store(G_TS_TERMINATED, std::memory_order_release);

		return Result;
	}

	// Description: Constructor
	// Return:
	// Notes:
	// ----------------------------------------------------
	GThread::GThread()
	{
		Id = 0;
		Handle = NULL;
		Parameters = NULL;
		
		State.store(G_TS_RELEASED, std::memory_order_release);
		Priority.store(G_TP_NORMAL, std::memory_order_release);
	}

	// Description: Destructor
	// Return:
	// Notes: Releases the thread!
	// ----------------------------------------------------
	GThread::~GThread()
	{
	}

	// Description: Returns the actual handle
	// Return:
	// Notes:
	// ----------------------------------------------------
	void* GThread::GetHandle() const
	{
		return Handle;
	}

	// Description: Resturns thread id.
	// Return:
	// Notes:
	// ---------------------------------------------------
	GUInt32 GThread::GetId() const
	{
		return Id;
	}

	// Description: Returns state of the thread
	// Return:
	// Notes:
	// ---------------------------------------------------
	GThreadState GThread::GetState() const
	{
		return State.load(std::memory_order_acquire);
	}

	// Description: Resturns thread priority
	// Return:
	// Notes:
	// ---------------------------------------------------
	GThreadPriority GThread::GetPriority() const
	{
		return Priority.load(std::memory_order_acquire);;
	}

	// Description: Returns entry method
	// Return:
	// Notes:
	// ---------------------------------------------------
	GEntryMethod GThread::GetEntryMethod() const
	{
		return EntryMethod;
	}

	// Description: Returns thread parameters.
	// Return:
	// Notes:
	// ---------------------------------------------------
	void* GThread::GetParameters() const
	{
		return Parameters;
	}

	// Description: Lets user to check if the thread is created
	// Return: True if created, false otherwise
	// Notes:
	bool GThread::IsCreated() const
	{
		return Handle != NULL;
	}

	bool GThread::IsRunning() const
	{
		return GetState() == G_TS_RUNNING;
	}

	// Description: Returns the current thread if it is created with a GThread
	// Return:
	// Notes:
	// ----------------------------------------------------
	GThread* GThread::GetCurrentThread()
	{
		GUtil::GError::DebugCheck(ThisThread == NULL, "This thread is not creted with GThread interface.");

		return ThisThread;
	}

}